package com.aispeech.testcustom.utils;

import com.aispeech.aios.BaseNode;
import com.aispeech.aios.BusClient;
import com.aispeech.aios.common.config.KEYS;
import com.aispeech.testcustom.TiApplication;
import com.aispeech.testcustom.bean.WakeupInfoBean;
import com.aispeech.testcustom.i.GetWakeupListener;

import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by rain on 2016/12/11.
 * get something infor from bus
 */
public class TestNode extends BaseNode {
    private static TestNode          mInstance;
    public         String            majorWakeup;
    private        String            isAEC;//disable or enable
    public         GetWakeupListener wakeupListener;

    private int channel_count = 1;

    private CircularFifoQueue<byte[]> originalPcmCircular;
    private CircularFifoQueue<byte[]> aecPcmCircular;

    private int originalCcLength  ;
    private int aecCcLength  ;

    public void setOriginalCcLength(int originalCcLength) {
        this.originalCcLength = originalCcLength;
    }

    private TestNode() {
    }

    public static synchronized TestNode getInstance() {
        if (null == mInstance) {
            mInstance = new TestNode();
        }
        return mInstance;
    }

    //初始化参数都在注册后生效
    public void registerWakeupListener(GetWakeupListener wakeupListener) {
        this.wakeupListener = wakeupListener;


        originalCcLength = Integer.parseInt(PreferenceUtil.getString(TiApplication.getContext(),PreferenceUtil.SAVE_ORIGINAL_MSWAKE_AUDIO,"20"));
        aecCcLength = Integer.parseInt(PreferenceUtil.getString(TiApplication.getContext(),PreferenceUtil.SAVE_AEC_MSWAKE_AUDIO,"60"));

        TiLog.d("set audio length -- originalCcLength:" + originalCcLength + "  aecCcLength:" + aecCcLength);
        originalPcmCircular = new CircularFifoQueue<>(originalCcLength);
        aecPcmCircular = new CircularFifoQueue<>(aecCcLength);
    }

    //停止测试
    public void unRegisterWakeupListener() {

        this.wakeupListener = null;
        originalPcmCircular = null;
        aecPcmCircular = null;
    }

    @Override
    public String getName() {
        return "test";
    }

    @Override
    public void onJoin() {
        super.onJoin();
        bc.subscribe("aec.pcm");
        bc.subscribe("recorder.pcm");
        bc.subscribe("recorder.state");
        bc.subscribe("vad.speech");
        bc.subscribe("vad.state");
        bc.subscribe("sdk.customize.shortcut.wakeup.effect");
        bc.subscribe("wakeup.command");
        bc.subscribe("wakeup.result");

        TiLog.d("TestNode onJoin: testNode节点已连接");

        majorWakeup = getKeysValue(KEYS.ADAPTER.WAKEUP_WORDS_MAJOR);//获取主唤醒词
        TiLog.d("onJoin: 获取主唤醒词-" + majorWakeup);
        isAEC = getKeysValue("/keys/switch/aec");//获取aec状态
        TiLog.d("onJoin: 获取aec状态-" + isAEC);


    }

    @Override
    public BusClient.RPCResult onCall(String s, byte[]... bytes) throws Exception {
        TiLog.d("onCall() called with: " + "s = [" + s + "], bytes = [" + bytes + "]");

        return null;
    }

    String wakeupName     = "";
    String wakeInfo       = "";
    String oneMajorWakeup = "";
    public WakeupInfoBean wakeupInfoBean;

    @Override
    public void onMessage(String topic, byte[]... parts) throws Exception {
        // super.onMessage(topic, parts);

        if ("recorder.pcm".equals(topic)) {
            //
            //parts[0] is voice data ; length is 1024
            //TiLog.d( " parts[0].length -" + parts[0].length);
            if (null != wakeupListener) {
                //originalPcmCircular.add(parts[0]);
                if (channel_count == 1 && null != originalPcmCircular) {
                    originalPcmCircular.add(parts[0]);
                }
                aecPcmCircular.add(parts[0]);
            }

        } else if ("aec.pcm".equals(topic)) {
            //
            //parts[0] is "stereo".getBytes()
            //parts[1] is voice data ; length is 6400
            //TiLog.d( " parts[0] -" + new String(parts[0]));//stereo
            //TiLog.d( "  parts[1].length -" + parts[1].length);
            if (null != wakeupListener) {
                channel_count = 2;
                if (null != originalPcmCircular) {
                    originalPcmCircular.add(parts[1]);
                }
            }
        } else if ("sdk.customize.shortcut.wakeup.effect".equals(topic)) {
            //自定义快捷唤醒了
            TiLog.d("自定义快捷唤醒出发");
            wakeupName = new String(parts[0]).trim().replace(" ", "");

            if (null != wakeupListener) {
                wakeupListener.wakeupCallBack("sdk.customize.shortcut.wakeup.effect", wakeupName);
                //保存音频
                FileUtils.SaveWavFileFromWakeup(aecPcmCircular, originalPcmCircular,
                        wakeupName, isAEC.equals("enable"), System.currentTimeMillis());

                aecPcmCircular.clear();
                originalPcmCircular.clear();
            }

        } else if ("wakeup.command".equals(topic)) {
            //系统自带快捷唤醒
            TiLog.d("系统自带唤醒出发");
            wakeupName = new String(parts[0]).trim().replace(" ", "");

            if (null != wakeupListener) {
                wakeupListener.wakeupCallBack("wakeup.command", wakeupName);
                //保存音频             }
                FileUtils.SaveWavFileFromWakeup(aecPcmCircular, originalPcmCircular,
                        wakeupName, isAEC.equals("enable"), System.currentTimeMillis());


                aecPcmCircular.clear();
                originalPcmCircular.clear();
            }


        } else if ("wakeup.result".equals(topic)) {
            //主唤醒回调
            wakeInfo = new String(parts[0], "UTF-8");

            TiLog.d("主唤醒触发");
            TiLog.i("唤醒参数:" + wakeInfo);
            if (majorWakeup.contains(wakeInfo)) {
                TiLog.d("该情况是唤醒后再说唤醒词出现,不保存音频!");

            } else {

                //                if (null == wakeupInfoBean){
                //                    TiLog.d("wakeupinfo --gson--> bean");
                ////                    Gson gson = new Gson();
                ////                    wakeupInfoBean = gson.fromJson(wakeInfo,WakeupInfoBean
                // .class);
                //                }

                JSONObject jsonObject = new JSONObject(wakeInfo);
                oneMajorWakeup = jsonObject.get("wakeupWord").toString();

                if (null == wakeupInfoBean) {
                    Iterator<String> keys = jsonObject.keys();
                    wakeupInfoBean = new WakeupInfoBean();
                    while (keys.hasNext()) {
                        String k = keys.next().toString();
                        TiLog.d(k + ":" + jsonObject.get(k).toString());
                        if (k.equals("confidence")) {
                            wakeupInfoBean.setConfidence(jsonObject.get(k).toString());
                        } else if (k.equals("frame")) {
                            wakeupInfoBean.setFrame(jsonObject.get(k).toString());
                        } else if (k.equals("lib_version")) {
                            wakeupInfoBean.setLib_version(jsonObject.get(k).toString());
                        } else if (k.equals("status")) {
                            wakeupInfoBean.setStatus(jsonObject.get(k).toString());
                        } else if (k.equals("vad_version")) {
                            wakeupInfoBean.setVad_version(jsonObject.get(k).toString());
                        } else if (k.equals("version")) {
                            wakeupInfoBean.setVersion(jsonObject.get(k).toString());
                        } else if (k.equals("wakeupWord")) {
                            wakeupInfoBean.setWakeupWord(jsonObject.get(k).toString());
                        } else if (k.equals("words")) {
                            JSONObject wordsJo = new JSONObject(jsonObject.get(k).toString());
                            Iterator<String> wkeys = wordsJo.keys();
                            Map<String, Float> wmap = new Hashtable<>();
                            while (wkeys.hasNext()) {
                                String wk = wkeys.next().toString();
                                wmap.put(wk, Float.parseFloat(wordsJo.get(wk).toString()));
                            }
                            wakeupInfoBean.setWords(wmap);
                        }
                    }
                }

                if (null != wakeupListener) {

                    wakeupListener.wakeupCallBack("wakeup.result", oneMajorWakeup.trim().replace(" ", "") == "" ? majorWakeup : oneMajorWakeup.trim());
                    //保存音频
                    FileUtils.SaveWavFileFromWakeup(aecPcmCircular, originalPcmCircular,
                            oneMajorWakeup.trim().replace(" ", "") == "" ? majorWakeup : oneMajorWakeup.trim(),
                            isAEC.equals("enable"), System.currentTimeMillis());

                    aecPcmCircular.clear();
                    originalPcmCircular.clear();

                } else {
                    TiLog.w("wakeupListener is null!");
                }
            }

        }

    }

    /**
     * 最好在node start之后再调用 , 避免bc为空
     *
     * @param key 需要获取的值的key
     * @return
     */
    public String getKeysValue(String key) {

        if (null != mInstance.bc) {

            BusClient.RPCResult rpc = mInstance.bc.call(key, "get");
            if (null != rpc) {
                try {
                    return new String((rpc.retval == null) ? "unknow".getBytes() : rpc.retval,
                            "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    return "getError";
                }

            }
        }
        return "nodeNotReady";
    }

}
